package cn.orangeframe.neon.domain.entity;

import cn.orangeframe.neon.domain.enums.TaskType;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import lombok.*;

import java.util.*;

@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WorkflowDef extends Auditable {

    @NotEmpty(message = "流程定义name不可为空")
    private String name;

    private String description;

    private int version = 1;

    @NotEmpty(message = "流程定义任务集合不可为空")
    private List<@Valid WorkflowTask> tasks = new LinkedList<>();

    private Map<String, Object> outputParameters = new HashMap<>();

    /**
     * 获取下一个任务
     * @param taskReferenceName 任务引用名称
     * @return WorkflowTask
     */
    public WorkflowTask getNextTask(String taskReferenceName) {
        WorkflowTask workflowTask = getTaskByRefName(taskReferenceName);
        if (workflowTask != null && TaskType.TERMINATE.name().equals(workflowTask.getType())) {
            return null;
        }

        Iterator<WorkflowTask> it = tasks.iterator();
        while (it.hasNext()) {
            WorkflowTask task = it.next();
            if (task.getTaskReferenceName().equals(taskReferenceName)) {
                break;
            }
            WorkflowTask nextTask = task.next(taskReferenceName, null);
            if (nextTask != null) {
                return nextTask;
            }

            if (task.has(taskReferenceName)) {
                break;
            }
        }
        if (it.hasNext()) {
            return it.next();
        }
        return null;
    }

    /**
     * 根据任务引用名称获取任务
     * @param taskReferenceName 任务引用名称
     * @return WorkflowTask
     */
    public WorkflowTask getTaskByRefName(String taskReferenceName) {
        return collectTasks().stream()
                .filter(workflowTask -> workflowTask.getTaskReferenceName().equals(taskReferenceName))
                .findFirst()
                .orElse(null);
    }

    /**
     * 递归收集所有任务
     * @return List<WorkflowTask>
     */
    public List<WorkflowTask> collectTasks() {
        List<WorkflowTask> tasks = new LinkedList<>();
        for (WorkflowTask workflowTask : this.tasks) {
            tasks.addAll(workflowTask.collectTasks());
        }
        return tasks;
    }
}
